package com.hqyj.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hqyj.pojo.WebSocketInfo;
import com.hqyj.utile.JsonFormatUtil;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

/**
 * @Description
 * @Autor 伍军
 * @Date 2022/9/26 15:26
 * @Version 1.0
 **/
@Component
@ServerEndpoint(value = "/helloWs")//地址： 只能前端定义websocoket对象访问，浏览器不能直接访问
public class HelloWebSocket {

    //记录所有会话
    private static List<Session>  list = new LinkedList<>();
    //记录在线用户名和会话ID
    private static List<WebSocketInfo>  listName = new LinkedList<>();

    //创建一个客户端触发的事件
    //session 会话，一个客户端对应一个session
    @OnOpen
    public void onOpen(Session s){
        System.out.println(s.getId()+"已经上线了");
        //记录session
        list.add(s);
    }

    //关闭一个客户端触发的事件
    @OnClose
    public void onClose(Session s){

        System.out.println(s.getId()+"已经下线了");
        list.remove(s);
        for(WebSocketInfo ws:listName){
            if(ws.getSessionId().equals(s.getId())){
                //删除
                listName.remove(ws);
            }
        }

    }

    //接收客户端发送的消息
    @OnMessage
    public void onMessage(Session s,String msg) throws IOException {
        System.out.println("客户端"+s.getId()+"发送的消息是:"+msg);
        //把json字符串转换成对象
        WebSocketInfo ws = JsonFormatUtil.getObject(msg);
        if(ws.getState()==0){
            //群聊
            groupChat(s, ws.getInfo());
        }else if(ws.getState()==2){
           //发送用户名
            sendName(s,ws.getName());
        } else{
            //私聊
            privateChat(s,ws.getInfo(),ws.getSessionId());
        }

    }

    /**
     * 发送用户名
     * @param s 用户名对应的ID
     * @param name 用户名
     * @throws IOException
     */
    public void sendName(Session s,String name) throws IOException {

        WebSocketInfo ws = new WebSocketInfo();
        ws.setName(name);
        ws.setSessionId(s.getId());
        ws.setState(2);
        listName.add(ws);
        ObjectMapper objectMapper = new ObjectMapper();
        String str = objectMapper.writeValueAsString(listName);
        //群发
        //服务端发送消息给所有客户端
        for(Session ss:list){
            //判断客户端是否上线
            if(ss.isOpen()){
                //发送消息给所有上线的客户端
                ss.getBasicRemote().sendText(str);
            }
        }
    }

    /**
     *
     * @param s 发送者 会话
     * @param msg  消息
     * @param privateId 接受者 Id
     * @throws IOException
     */
    public void privateChat(Session s,String msg,String privateId) throws IOException {
        //消息封装
        WebSocketInfo ws = new WebSocketInfo();
        ws.setSessionId(s.getId());
        ws.setInfo(msg);

        //服务端发送消息给所有客户端
        for(Session ss:list){
            //判断客户端是否上线
            if(ss.isOpen()){
                if(ss.getId().equals(privateId)){
                    //发送消息给指定人的客户端
                    ss.getBasicRemote().sendText(JsonFormatUtil.getStr(ws));
                }

            }
        }
    }

    //群聊
    public void groupChat(Session s,String msg) throws IOException {
        //消息封装
        WebSocketInfo ws = new WebSocketInfo();
        ws.setSessionId(s.getId());
        ws.setInfo(msg);

        //服务端发送消息给所有客户端
        for(Session ss:list){
            //判断客户端是否上线
            if(ss.isOpen()){
                //发送消息给所有上线的客户端
                ss.getBasicRemote().sendText(JsonFormatUtil.getStr(ws));
            }
        }
    }

    //异常触发的事件
    @OnError
    public void onError(Session s,Throwable  t){
        System.out.println("客户端"+s.getId()+"出现异常："+t.getMessage());
    }


}
